﻿using ICSharpCode.AvalonEdit.Highlighting;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Management.Automation;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;


namespace AESUtil
{
    /// <summary>
    /// sendRequest.xaml 的交互逻辑
    /// </summary>
    public partial class SendRequest : Window
    {
        private bool isReqStr = true;
        ObservableCollection<RequestItem> historyList = null;

        public SendRequest()
        {
            InitializeComponent();
            this.historyList = new ObservableCollection<RequestItem>(RequestHistoryUtil.getHistory());
            this.historyListBox.ItemsSource = this.historyList;
            if (MainGrid.ColumnDefinitions[2].Width.Value > 0)
            {
                this.displayHistoryBtn.Content = "隐藏历史记录";
            }
            else
            {
                this.displayHistoryBtn.Content = "显示历史记录";
            }
        }

        private async void sendRequest_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                await Task.Run(() =>
                {
                    this.Dispatcher.Invoke(() =>
                    {
                        this.sendRequest.IsEnabled = false;
                    });
                });
                using (PowerShell ps = PowerShell.Create())
                {
                    ps.AddScript("chcp 65001").Invoke();
                    ps.AddScript("[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }").Invoke();
                    ps.AddScript(getUTF8Result(this.paramsBox.Text));

                    Collection<PSObject> results = null;
                    await Task.Run(()=> { results = ps.Invoke(); });
                    StringBuilder stringBuilder = new StringBuilder();
                    if (ps.HadErrors)
                    {
                        foreach (var error in ps.Streams.Error)
                        {
                            stringBuilder.AppendLine(error.ToString());
                        }
                    }
                    else
                    {
                        foreach (PSObject result in results)
                        {
                            stringBuilder.AppendLine(result.ToString());
                        }
                    }
                    this.SetResultBoxText(JsonUtil.ConvertFormatJsonString(stringBuilder.ToString()));
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show("出现异常，请检查请求内容是否正确：" + ex.ToString());
            }
            finally
            {
                this.sendRequest.IsEnabled = true;
            }
        }
        private String getUTF8Result(String oriText)
        {
            if (oriText.Contains("Invoke-WebRequest"))
            {
                String result  =  oriText.Insert(oriText.IndexOf("Invoke-WebRequest"), "$response = ");
                result = result + "\n[System.Text.Encoding]::UTF8.GetString($response.RawContentStream.ToArray())";
                return result;
            }
            return oriText;
        }

        public static (string Uri, string Method) ExtractUriAndMethod(string powerShellScript)
        {
            if (string.IsNullOrWhiteSpace(powerShellScript))
                return (null, null);

            // 匹配 -Uri "实际的URL"
            string uriPattern = @"-Uri\s+""(?<uri>[^""]+)""";
            var uriMatch = Regex.Match(powerShellScript, uriPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
            string uri = uriMatch.Success ? uriMatch.Groups["uri"].Value : null;

            // 匹配 -Method "POST" 或 -Method 'GET' 等
            string methodPattern = @"-Method\s+['""](?<method>[^'""]+)['""]";
            var methodMatch = Regex.Match(powerShellScript, methodPattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
            string method = methodMatch.Success ? methodMatch.Groups["method"].Value : null;

            return (uri, method);
        }

        private void paramsBox_TextChanged(object sender, EventArgs e)
        {
            var (uri, post) = ExtractUriAndMethod(this.paramsBox.Text);
            this.urlTextBox.Text = uri;
            this.methodTextBox.Text = post;
            this.paramsOnlyBox.Text = JsonUtil.ConvertFormatJsonString(ExtractBody(this.paramsBox.Text));
            string JWT = ExtractJWT(this.paramsBox.Text);
            var( type,info ) = getJwtInfo(JWT);
            this.userTextBox.Text = info;
        }
        private void paramsOnlyBox_TextChanged(object sender, EventArgs e)
        {
            string paramsText = this.paramsOnlyBox.Text;
            if (!string.IsNullOrWhiteSpace(paramsText)) {
                if (paramsText[0] == '{' && paramsText[paramsText.Length - 1] == '}')
                {

                    string start;
                    if (Properties.Settings.Default.autoFormat)
                    {
                        start = "\"req\": \"";
                    }
                    else {
                        start = "\"req\":\"";
                    }

                    if(paramsText.IndexOf(start)>0)
                    {
                        int index = paramsText.IndexOf(start) + start.Length;
                        int fix = Properties.Settings.Default.autoFormat ? 4 : 2;
                        paramsText = paramsText.Substring(index, paramsText.Length - index - fix);
                        this.paramsOnlyDecryptBox.Text = JsonUtil.ConvertFormatJsonString(SM4Util.DecryptUseDefaultKEYIV(paramsText));
                        this.isReqStr = true;
                    }
                }
                else
                {
                    this.paramsOnlyDecryptBox.Text = JsonUtil.ConvertFormatJsonString(AESUtils.DecryptUseDefaultKeyIV(paramsText));
                    this.isReqStr = false;
                }
            }
        }
        private (string type,string info) getJwtInfo(String oriJWT)
        {
            if (!string.IsNullOrEmpty(oriJWT) && oriJWT.Split('.').Length > 1)
            {
                string info = JsonUtil.ConvertFormatJsonString(Base64Util.getStringFromBase64String(oriJWT.Split('.')[1]));
                return (null, info);
            }else
            {
                return (null, null);
            }
        }
        public static string ExtractBody(string script)
        {
            if (string.IsNullOrWhiteSpace(script))
                return null;

            // 匹配 -Body 后面的字符串，支持双引号和单引号，支持跨行（` 换行）
            // 使用 [\s\S] 来匹配所有字符（包括换行），直到遇到非转义的引号结尾
            string pattern = @"-Body\s+[""'](?<body>(?:[^(`""')]|`[""']|`[\r\n])+?)[""']";

            var match = Regex.Match(script, pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
            if (!match.Success)
                return null;

            string encodedBody = match.Groups["body"].Value;

            // 还原 PowerShell 中的转义序列
            string decodedBody = DecodePowerShellString(encodedBody);

            return decodedBody;
        }
        public static string ReplaceBody(string script,string replacement)
        {
            if (string.IsNullOrWhiteSpace(script))
                return script;

            // 匹配 -Body 后面的字符串，支持双引号和单引号，支持跨行（` 换行）
            // 使用 [\s\S] 来匹配所有字符（包括换行），直到遇到非转义的引号结尾
            string pattern = @"-Body\s+[""'](?<body>(?:[^(`""')]|`[""']|`[\r\n])+?)[""']";

            replacement = "-Body \"" + replacement.Replace("\"", "`\"") + "\"";
            return Regex.Replace(script, pattern, replacement, RegexOptions.IgnoreCase | RegexOptions.Singleline);

        }
        public static String ExtractJWT(string script)
        {
            if (string.IsNullOrWhiteSpace(script))
                return null;
            string pattern = @"""Authorization""\s*=\s*""([^""]+)""";

            var match = Regex.Match(script, pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
            if (!match.Success)
                return null;

            string JWT = match.Groups[1].Value;

            JWT = DecodePowerShellString(JWT);

            return JWT;
        }

        /// <summary>
        /// 还原 PowerShell 字符串中的 `` ` `` 转义字符
        /// </summary>
        /// <param name="input">转义后的字符串</param>
        /// <returns>还原后的字符串</returns>
        private static string DecodePowerShellString(string input)
        {
            if (string.IsNullOrEmpty(input)) return input;

            return input
                .Replace("`\"", "\"")     // `"  -> "
                .Replace("`'", "'")       // `'  -> '
                .Replace("`$", "$")       // `$  -> $
                .Replace("``", "`")       // ``  -> `
                .Replace("`n", "\n")      // `n  -> newline
                .Replace("`r", "\r")      // `r  -> carriage return
                .Replace("`t", "\t")      // `t  -> tab
                .Replace("`b", "\b");     // `b  -> backspace
        }

        private void clearResult_Click(object sender, RoutedEventArgs e)
        {
            this.SetResultBoxText("");
        }
        private void SetResultBoxText(string text)
        {
            if (text == null)
            {
                this.resultBox.Text = "";
                return;
            }
            if(text.Length > 80000)
            {
                this.resultBox.SyntaxHighlighting = null;
            }
            else if(this.resultBox.SyntaxHighlighting == null) 
            {
                this.resultBox.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("Json");
            }
            this.resultBox.Text = text;
        }

        private void updateEditedParams_Click(object sender, RoutedEventArgs e)
        {
            if (this.isReqStr) {
                string para = JsonUtil.ConvertOriJsonString(this.paramsOnlyDecryptBox.Text);
                string newParam = "{\"req\":\"" + SM4Util.EncryptUseDefaultKEYIV(para) + "\"}";
                this.paramsBox.Text = ReplaceBody(this.paramsBox.Text, newParam);
            }
            else
            {
                string para = JsonUtil.ConvertOriJsonString(this.paramsOnlyDecryptBox.Text);
                string newParam = AESUtils.EncryptUseDefaultKeyIV(para);
                this.paramsBox.Text = ReplaceBody(this.paramsBox.Text, newParam);
            }
        }

        private void displayHistory_Click(object sender, RoutedEventArgs e)
        {
            if (MainGrid.ColumnDefinitions[2].Width.Value>0)
            {
                MainGrid.ColumnDefinitions[2].Width = new GridLength(0);
                this.displayHistoryBtn.Content = "显示历史记录";
            }
            else
            {
                MainGrid.ColumnDefinitions[2].Width = new GridLength(200);
                this.displayHistoryBtn.Content = "隐藏历史记录";
            }
        }

        private void historyList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            RequestItem item = this.historyListBox.SelectedItem as RequestItem;
            if (item != null) {
                this.paramsBox.Text = item.requestStr;
                this.SetResultBoxText(JsonUtil.ConvertFormatJsonString(item.resultStr));
            }
        }

        private void saveToHistory_Click(object sender, RoutedEventArgs e)
        {
            if (!string.IsNullOrEmpty(this.paramsBox.Text))
            {
                SetHistoryName shn = new SetHistoryName();
                shn.Owner = this;
                shn.name = this.urlTextBox.Text.Substring(this.urlTextBox.Text.LastIndexOf("/") + 1);
                bool? dialogResult = shn.ShowDialog();
                if (dialogResult == true)
                {
                    RequestItem item = new RequestItem();
                    item.Name = shn.name;
                    item.requestStr = this.paramsBox.Text;
                    item.resultStr = JsonUtil.ConvertOriJsonString( this.resultBox.Text);
                    this.historyList.Add(item);                
                    RequestHistoryUtil.updateHistory(this.historyList.ToList());
                }

            }
        }

        private void clearHistory_Click(object sender, RoutedEventArgs e)
        {
            MessageBoxResult result = System.Windows.MessageBox.Show("确认要所有历史记录么？","确认删除", MessageBoxButton.OKCancel, MessageBoxImage.Question);
            if (result == MessageBoxResult.OK)
            {
                this.historyList.Clear();
                RequestHistoryUtil.updateHistory(this.historyList.ToList());
            }
        }

        private void deleteSeletedHistory_Click(object sender, RoutedEventArgs e)
        {
            MessageBoxResult result = System.Windows.MessageBox.Show("确认要清除选中的历史记录么？", "确认删除", MessageBoxButton.OKCancel, MessageBoxImage.Question);
            if (result == MessageBoxResult.OK)
            {
                List<RequestItem> list = new List<RequestItem>();
                foreach (var item in this.historyListBox.SelectedItems)
                {
                    RequestItem requestItem = item as RequestItem;
                    list.Add(requestItem);
                }
                foreach (var item in list)
                {
                    this.historyList.Remove(item);
                }

                RequestHistoryUtil.updateHistory(this.historyList.ToList());

            }
        }
    }
}
